﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using CustomException;
using Global;
using Helper;

namespace Display
{
    public partial class TestReminder : Form
    {
        #region Code for Drag the form
        [DllImport("user32.dll")]
        private static extern bool PostMessage(IntPtr hWnd, int msg, long wParam, long lParam);
        // To store the location of previous mouse left click in the form
        // so that we can use it to calculate the new form location during dragging
        private Point prevLeftClick;

        // To determine if it is the first time entry for every dragging of the form
        private bool isFirst = true;

        // Acts like a gate to do allow or deny
        private bool toBlock = true;
        private void pnTop_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                const int HTCAPTION = 2;
                const int WM_NCLBUTTONDOWN = 161;

                int ix = e.X & 0xffff;
                int iy = e.Y & 0xffff;
                long ll = ix | iy << 16;

                PostMessage(this.pnTop.Handle, WM_NCLBUTTONDOWN, HTCAPTION, ll);
            }
        }
        private void pnTop_MouseMove(object sender, MouseEventArgs e)
        {
            // Check if dragging of the form has occurred
            if (e.Button == MouseButtons.Left)
            {
                // If this is the first mouse move event for left click dragging of the form,
                // store the current point clicked so that we can use it to calculate the form's
                // new location in subsequent mouse move events due to left click dragging of the form
                if (isFirst == true)
                {
                    // Store previous left click position
                    prevLeftClick = new Point(e.X, e.Y);

                    // Subsequent mouse move events will not be treated as first time, until the
                    // left mouse click is released or other mouse click occur
                    isFirst = false;
                }

                // On subsequent mouse move events with left mouse click down. (During dragging of form)
                else
                {
                    // This flag here is to allow alternate processing for dragging the form because it
                    // causes serious flicking when u allow every such events to change the form's location.
                    // You can try commenting this out to see what i mean
                    if (toBlock == false)
                        this.Location = new Point(this.Location.X + e.X - prevLeftClick.X, this.Location.Y + e.Y - prevLeftClick.Y);

                    // Store new previous left click position
                    prevLeftClick = new Point(e.X, e.Y);

                    // Allow or deny next mouse move dragging event
                    toBlock = !toBlock;
                }
            }

            // This is a new mouse move event so reset flag
            else
                isFirst = true;
        }
        #endregion

        #region Initialize
        enum State
        {
            START,
            FADEIN,
            FADEOUT
        }

        //user controls
        private VocabularyUC vocabularyUC;
        private NoteUC noteUC;
        private System.Timers.Timer tmrFade = new System.Timers.Timer();
        private State state;
        private bool _hasNoItem = true;
        private bool IsCurrentVocabulary = true;
        private Random _random = new Random();
        public bool IsNoItem
        {
            get { return this._hasNoItem; }
            set { _hasNoItem = value; }
        }
        public void InitUserControls()
        {
            if (Settings.IS_VOCABULARY == true)
            {
                this.vocabularyUC = new VocabularyUC();
                this.vocabularyUC.LoadItems();
                this.vocabularyUC.Location = new Point(5, 25);
                this.vocabularyUC.Name = "vocabularyUC";
                this.vocabularyUC.Enabled = true;
                this.vocabularyUC.Visible = false;
                this.Controls.Add(vocabularyUC);
            }

            if (Settings.IS_NOTE == true)
            {
                this.noteUC = new NoteUC();
                this.noteUC.LoadItems();
                this.noteUC.Location = new Point(5, 25);
                this.noteUC.Name = "noteUC";
                this.noteUC.Enabled = true;
                this.noteUC.Visible = false;
                this.Controls.Add(noteUC);
            }
        }
        public void InitTimers()
        {
            this.tmrMain.Interval = Settings.WAITING_TIME * 1000;
            this.tmrFade.Enabled = false;
            this.tmrFade.Interval = 20;
            this.tmrFade.SynchronizingObject = this;
            this.tmrFade.Elapsed += new System.Timers.ElapsedEventHandler(this.tmrFade_Elapsed);
        }
        public TestReminder()
        {
            InitializeComponent();
            InitUserControls();
            ValidateUserControls();
            InitTimers();
            HideUserControls();

            this.TopMost = true;
            this.Opacity = 0;
            this.state = State.START;
        }
        #endregion

        #region Events handling

        private void tmrFade_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            switch (state)
            {
                case State.FADEIN:
                    if (FadeIn() == true)   //finish fade in
                    {
                        this.state = State.FADEOUT; //ready to fade out
                        tmrFade.Enabled = false;
                        tmrMain.Interval = Settings.DISPLAY_TIME * 1000;
                        tmrMain.Enabled = true;
                    }
                    break;

                case State.FADEOUT:
                    if (FadeOut() == true)  //finish fade out
                    {
                        this.state = State.START;
                        //Delete the current item
                        if (cbRemove.Checked)
                            this.DeleteItem();

                        tmrFade.Enabled = false;
                        tmrMain.Interval = Settings.WAITING_TIME * 1000;
                        tmrMain.Enabled = true;
                    }
                    break;
            }
        }

        private void tmrMain_Tick(object sender, EventArgs e)
        {
            cbRemove.Checked = false;

            switch (state)
            {
                case State.START:
                    if (vocabularyUC != null && noteUC != null)
                    {
                        vocabularyUC.Visible = false;
                        noteUC.Visible = false;

                        switch (MainFormHelper.GetRandom(vocabularyUC.Count, noteUC.Count))
                        {
                            case Constant.CURRENT_ITEM.VOCABULARY:
                                IsCurrentVocabulary = true;
                                vocabularyUC.Visible = true;
                                vocabularyUC.Next();
                                break;
                            case Constant.CURRENT_ITEM.NOTE:
                                IsCurrentVocabulary = false;
                                noteUC.Visible = true;
                                noteUC.Next();
                                break;
                        }
                    }
                    else if (vocabularyUC != null)
                    {
                        IsCurrentVocabulary = true;
                        vocabularyUC.Visible = true;
                        vocabularyUC.Next();
                    }
                    else if (noteUC != null)
                    {
                        IsCurrentVocabulary = false;
                        noteUC.Visible = true;
                        noteUC.Next();
                    }

                    tmrFade.Enabled = true;
                    tmrMain.Enabled = false;
                    this.Size = new Size(0, 0);
                    state = State.FADEIN;
                    break;

                case State.FADEIN:
                case State.FADEOUT:
                    tmrFade.Enabled = true;
                    tmrMain.Enabled = false;
                    break;
            }
        }

        private void pnTop_MouseEnter(object sender, EventArgs e)
        {
            this.Opacity = 1;
            this.tmrFade.Enabled = false;
        }

        private void pnTop_MouseLeave(object sender, EventArgs e)
        {
            this.tmrFade.Enabled = true;
        }

        #endregion

        #region Code of internal methods
        private bool FadeIn()
        {
            this.Opacity += 0.009;
            if (this.Opacity >= .95)
            {
                this.Opacity = 1;
                return true;
            }
            return false;
        }
        private bool FadeOut()
        {
            this.Opacity -= 0.009;
            if (this.Opacity <= 0)
            {
                this.Opacity = 0;
                return true;
            }
            return false;
        }
        private void HideUserControls()
        {
            if (this.vocabularyUC != null)
                this.vocabularyUC.Visible = false;

            if (this.noteUC != null)
                this.noteUC.Visible = false;
        }
        public void MouseEnter()
        {
            this.Opacity = 1;
            this.tmrFade.Enabled = false;
        }
        public void MouseLeave()
        {
            this.tmrFade.Enabled = true;
        }
        private void ValidateUserControls()
        {
            if (noteUC == null && vocabularyUC == null)
            {
                this._hasNoItem = true;
                return;
            }

            var count = 0;
            if (noteUC != null)
                count = noteUC.Count;
            if (vocabularyUC != null)
                count += vocabularyUC.Count;

            if (count <= 0)
                this._hasNoItem = true;
            else
                this._hasNoItem = false;
        }
        private void CleanUp()
        {
            this.tmrFade.Dispose();
        }
        private void DeleteItem()
        {
            if (IsCurrentVocabulary)
                vocabularyUC.DeleteCurrentItem();
            else
                noteUC.DeleteCurrentItem();       
        }
        #endregion
    }
}
